package cn.wp.common.core.web.service;

import cn.hutool.core.util.ReflectUtil;
import cn.wp.common.core.Wp;
import cn.wp.common.core.exception.WpException;
import cn.wp.common.core.util.ApplicationContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * Service 统一调用入口
 *   注意：仅支持单进程内使用
 * Created by chenyb on 2019-10-14
 */
@RestController
@RequestMapping(Wp.WebContext + "/call/")
public class CallServiceController {

    @Autowired
    private ServiceConfigurations serviceConfigurations;

    /**
     * 调用Service
     * @return
     */
    @RequestMapping("/{nameSpace}/{serviceBeanName}/{method}")
    public Object callService(HttpServletRequest request,@PathVariable("serviceBeanName") String serviceBeanName,@PathVariable("method") String method){
        Object result = new Object();
        System.err.println("method:" + method);
        ServiceConfiguration serviceConfiguration = serviceConfigurations.getServiceConfiguration(serviceBeanName);
        if(serviceConfiguration != null){
            result = this.invokeMethod(serviceBeanName,method,serviceConfiguration,request);
        }else{
            throw new WpException("Service Bean [" + serviceBeanName + "] no register to ServiceConfigurations");
        };
        return result;
    };

    private <T> T invokeMethod(String serviceBeanName,String method,ServiceConfiguration serviceConfiguration,HttpServletRequest request){
        Object bean = ApplicationContextUtil.getContext().getBean(serviceBeanName);
        boolean isPost = ("POST".equalsIgnoreCase(request.getMethod()));

        boolean isExcludeMethod = serviceConfiguration.isExcludeMethod(method);
        if(isExcludeMethod){
            throw new WpException("Service Bean [" + serviceBeanName + "] Method [" + method + "] is ExcludeMethod");
        }

        boolean isPostMethod = serviceConfiguration.isPostMethod(method);
        if(isPostMethod){
            if(isPost){
                return ReflectUtil.invoke(bean,method);
            }else{
                throw new WpException("Service Bean [" + serviceBeanName + "] Method [" + method + "] is Post Method");
            }
        }else{
            List<String> methods = serviceConfiguration.getMethods();
            if(methods.size() > 0){
                boolean containsMethod = serviceConfiguration.containsMethod(method);
                if(containsMethod){
                    ReflectUtil.invoke(bean,method);
                }else{
                    throw new WpException("Service Bean [" + serviceBeanName + "] Method [" + method + "] is not register");
                }
            }else{
                return ReflectUtil.invoke(bean,method);
            }
        }

        return null;
    }

}